package cn.wzy.service.impl;

import cn.wzy.dto.LoginDTO;
import cn.wzy.enums.AppHttpCodeEnum;
import cn.wzy.enums.BaseConstants;
import cn.wzy.enums.WxConstants;
import cn.wzy.mapper.EmployeeMapper;
import cn.wzy.mapper.LogininfoMapper;
import cn.wzy.mapper.UserMapper;
import cn.wzy.mapper.WxuserMapper;
import cn.wzy.pojo.Employee;
import cn.wzy.pojo.Logininfo;
import cn.wzy.pojo.User;
import cn.wzy.pojo.Wxuser;
import cn.wzy.results.ResponseResult;
import cn.wzy.service.LoginService;
import cn.wzy.utils.HttpUtil;
import cn.wzy.utils.MD5Utils;
import cn.wzy.utils.RedisCache;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {


    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private RedisCache redisCache;
    @Resource
    private LogininfoMapper logininfoMapper;
    @Resource
    private WxuserMapper wxuserMapper;
    @Resource
    private UserMapper userMapper;
    /*
    * 登入
    * */
    @Override
    public ResponseResult loginAccount(LoginDTO loginDTO) {
//        数据校验
        // 1.1 null判断
        if (StringUtils.isEmpty(loginDTO.getUsername())
                ||StringUtils.isEmpty(loginDTO.getPassword())
                || loginDTO.getLoginType()==null)
            return ResponseResult.errorResult(203,"参数错误，请重新输入！");
//        判断是否有该用户
        LambdaQueryWrapper<Logininfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Logininfo::getType,loginDTO.getLoginType())
                .and((wrapper)->
                {wrapper.eq(Logininfo::getUsername,loginDTO.getUsername())
                        .or().eq(Logininfo::getPhone,loginDTO.getUsername());});
        Logininfo logininfo = logininfoMapper.selectOne(queryWrapper);
        if (logininfo==null)
            return ResponseResult.errorResult(204,"用户名或密码不正确！");
        if (logininfo.getDisable()==-1)
            return ResponseResult.errorResult(205,"账户已被冻结，请联系客服！");
        //比对密码完成登录
        String password = MD5Utils.encrypByMd5(loginDTO.getPassword()+logininfo.getSalt());
        if (!password.equals(logininfo.getPassword())){
            return ResponseResult.errorResult(204,"用户名或密码不正确！");
        }
//        返回前端token和用户
        Map<String, Object> result = getResult(logininfo);
        return ResponseResult.okResult(result);
    }

    private Map<String, Object> getResult(Logininfo logininfo) {
        String token = UUID.randomUUID().toString().replaceAll("-", "");
//        保存到rides
        redisCache.setCacheObject("User:" + token, logininfo, 30, TimeUnit.MINUTES);
//        返回token和Loginininfo
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        logininfo.setPassword("");
        logininfo.setSalt("");
        result.put("loginInfo", logininfo);
        return result;
    }

    /*
    * 退出登入
    * */
    @Override
    public ResponseResult loginOut(HttpServletRequest request) {
        String token = request.getHeader("token");
        redisCache.deleteObject("User:"+token);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult loginPhone(LoginDTO loginDTO) {
        // 1.1 null判断
        if (StringUtils.isEmpty(loginDTO.getUsername())
                ||StringUtils.isEmpty(loginDTO.getPassword())
                || loginDTO.getLoginType()==null)
            return ResponseResult.errorResult(203,"参数错误，请重新输入！");
        //        判断是否有该用户
        LambdaQueryWrapper<Logininfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Logininfo::getType,loginDTO.getLoginType())
                .and((wrapper)->
                {wrapper.eq(Logininfo::getPhone,loginDTO.getUsername());});
        Logininfo logininfo = logininfoMapper.selectOne(queryWrapper);
        if (logininfo==null)
            return ResponseResult.errorResult(204,"该手机号未注册，请注册后登入");
        if (logininfo.getDisable()==-1)
            return ResponseResult.errorResult(205,"账户已被冻结，请联系客服！");
//        验证码对比
        String loginCode = redisCache.getCacheObject(BaseConstants.RedisContants.LOGIN__SMS_CODE + loginDTO.getUsername());
        if (StringUtils.isEmpty(loginCode)){
            return ResponseResult.errorResult(206,"验证码过期，请重新发送");
        }
        if (!loginCode.equals(loginDTO.getPassword())){
            return ResponseResult.errorResult(207,"验证码输入错误，请重试！");
        }
        //        返回前端token和用户
        Map<String, Object> result = getResult(logininfo);
        return ResponseResult.okResult(result);

    }


    /*
    * wx登入
    * */
    @Override
    public ResponseResult loginWechat(Map<String, String> wechat) {
//        通过code获取到wx中的token
        String code = wechat.get("code");
        String ackUrl = WxConstants.GET_ACK_URL.replace("APPID",WxConstants.APPID).
                replace("SECRET",WxConstants.SECRET).replace("CODE",code);
        String token_opid = HttpUtil.httpGet(ackUrl);
//        转成json
        JSONObject tokenObj = JSONObject.parseObject(token_opid);
        String  access_token = (String) tokenObj.get("access_token");
        String openid = (String) tokenObj.get("openid");
//        通过token和opid在数据库查询wx用户
        LambdaQueryWrapper<Wxuser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Wxuser::getOpenid,openid);
        Wxuser wxuser = wxuserMapper.selectOne(queryWrapper);
//       判断wx是否存在
        if (Objects.isNull(wxuser)){
//            跳转到绑定手机,携带token和opid
            HashMap<String, String> tokenOpid = new HashMap<>();
            tokenOpid.put("accessToken",access_token);
            tokenObj.put("openid",openid);
            return ResponseResult.okResult(601,tokenOpid);
        }
//        存在 wx用户，直接免密登入
//        存登入信息并返回前端token和logininfo
        User user = userMapper.selectById(wxuser.getUserId());
        Logininfo logininfo = logininfoMapper.selectById(user.getLogininfoId());
        Map<String, Object> result = getResult(logininfo);
        return ResponseResult.okResult(result);
    }
}
